Particle Tutorials

Particle Tutorial 1: Learn how to create a simple particle fountain controlled by your mouse!

Step 1 - Basic-256 Boilerplate

The aim of this particle tutorial, is to build a simple particle fountain, controlled by mouse, from the ground up.
At every interim step, it is the intention to have a working program so that you can see what the results are of the piecemeal changes. You can either cut and paste the code in this document to the Basic-256 code window (although indentation gets lost.) or use the hyperlinks to the example programs.

What is a particle system?

A particle system in computer graphics is a technique used to simulate complex visual effects that are difficult to render with conventional methods. It involves creating a large number of small, simple objects (particles) and animating them to create the illusion of more complex, "fuzzy" phenomena like explosions, fire, smoke, sparks, waterfalls, clouds, fog, petals, grass, bubbles, and so on.

In this tutorial however, we will keep things a LOT simpler. In our particle system, each particle will have its own series of properties related to its behavior (for example, position, velocity, age, etc.). We will start our particle system from a blank slate

Basic-256 Boilerplate

For building up our particle system program, we will use the following scaffolding


Fastgraphics # write to video buffer.
size_x=800
size_y=800 # good practice to put every constant in a variable.
graphsize size_x,size_y # feel free to change the size of your canvas
color black
rect 0,0,size_x-1,size_y-1 # start out with a nice black screen.
refresh # dump the video buffer to screen
#Voila! This gives you a nice canvas to draw on.

          

Running this program gives us a nice black background. Not really exciting yet

Download Code
Particle01 Thumbnail
Step 2 - Our particle fountain

First, we need to define the specifics of our particle system. The particle system itself is stored into a multidimensional array, a grid if you like. The first element of the array denotes the number of particles in our system. (the number of lines on the grid) Here we will limit us to 300. (Feel free to adapt to the power of your system) The second denotes the number of properties each particle has. (the number of columns on the grid)
For an initial, minimal particle system, we will need x-position, y-position, x-velocity, y-velocity. This makes 4 properties in all.
We will set up the particle system to start from the centre, so x-position and y-position will be 400 (half of the 800x800 graphsize)
For the x- and y-velocities, we will take a very small number, here between -0.25 and 0.25.


Partnum=300
Dim Particle (Partnum,4) #particle system with 300 particles with 4 properties
for p = 0 to Partnum-1
  Particle[p,0] = size_x/2
  Particle[p,1]= size_y/2
  Particle[p,2]= (rand-0.5)/2 # velocity from -0.25 to 0.25
  Particle[p,3]= (rand-0.5)/2 #velocity from -0.25 to 0.25
next p

          

If we now dump our particles to the screen, we would just see a dot in the middle of a black screen as all particles are bunched up together. A particle system however is a dynamic system, so we will have to update it continually and reshow it.
We update our particle system by adding the velocities to the respective positions, we show the new screen and we clear it again. Finally we loop it with a simple goto-loop


Loop:
for p = 0 to Partnum-1 #write all the particles to the buffer and update them
  color white
  plot (Particle[p,0],Particle[p,1])
  Particle[p,0]= Particle[p,0]+Particle[p,2]
  Particle[p,1]= Particle[p,1]+Particle[p,3]
next p
Refresh #all particles shown updated on the screen
color black
rect 0,0, size_x-1,size_y-1 #initialize the screen to black again
goto Loop # do it all again

          

Now, if we run this program, we already get a nice star-burst effect, but it quickly fizzles out as most points move beyond the screen borders. (Feel free to change the number of particles and their velocities. Experimenting is fun!)

Download
Step 3 - Fixing the dissipating starburst (first option)

There are 2 easy ways to prevent this fizzling out, to keep the particle system constrained within the borders of the graphics area.
-/ We bounce the particles of the screen borders by reversing the velocity direction for the impacted screen border (either x-velocity or y-velocity). This however turn chaotic very quickly
-/ Once it moves out of view, we reinitialize the particle to the centre of our screen again

First Option
In the loop where we update the x- and y-positions, we check if the particle has moved off the screen. If so we reverse the direction:


for p = 0 to Partnum-1 #write the particles to the buffer and update them
  color white
  plot (Particle[p,0],Particle[p,1])
  Particle[p,0]= Particle[p,0]+Particle[p,2]
  if Particle[p,0] < 0 or Particle [p,0]>size_x then Particle[p,2]= -Particle[p,2]
  Particle[p,1]= Particle[p,1]+Particle[p,3]
  if Particle[p,1] < 0 or Particle [p,1]>size_y then Particle[p,3]= -Particle[p,3]
next p
          

If we now run the program with this updated loop, we quickly find us in a chaotic situation with particles bouncing all over the place.

Download
Step 4 - Stop the chaos

To stop the chaotic motion after the Particles start to bounce off the screen edges, we can do the following:
-/ add a bit of gravity (by slightly increasing the y-speed)
-/ dampen the bounce (by multiply y-speed with eg 0.7-0.9 when the particle 'bounces').

For the gravity, we add a gravity parameter next to the array definition and set it to eg 0.001. (This is because on my system, I get about 500 full iteration loops per second. As we add gravity at every loop, the gravity influencssystem very quickly. Again experiment with this.).

For the dampening and in order to get some variation in the bounce, we dampen the bounce with a factor between 0.7 and 0.9.
This leads us to the following code changes

		  
grav=0.001 # gravity increase
for p = 0 to Partnum-1 #write the particles to the buffer and update them
  color white
  plot (Particle[p,0],Particle[p,1])
  Particle[p,0]= Particle[p,0]+Particle[p,2]
  if Particle[p,0] < 0 or Particle [p,0]>size_x then   Particle[p,2]=-Particle[p,2]*(0.7+rand/5)
  Particle[p,1]= Particle[p,1]+Particle[p,3]
  if Particle[p,1] < 0 then Particle[p,3]= - Particle[p,3] # bounce off ceiling
  if Particle [p,1]>size_y then Particle[p,3]= - Particle[p,3]*(0.7+rand/5)bounce + dampen
  Particle[p,3]= Particle[p,3]+grav # artificial gravity
next p
          
Download
Step 5 - Fixing the dissipating starburst (second option)

In the second option to improve the simple starburst (disregarding the gravity addition), we have to prevent our particles from escaping the screen. We do this by reinitialising the particle to the centre of the screen if the particle has moved off the screen.


for p = 0 to Partnum-1 #write the particles to the buffer and update them
  color white
  plot (Particle[p,0],Particle[p,1])
  Particle[p,0]= Particle[p,0]+Particle[p,2]
  Particle[p,1]= Particle[p,1]+Particle[p,3]
  if Particle[p,0]< 0 or Particle [p,0]>size_x or Particle[p,1]< 0 or Particle [p,1]> size_y then
    Particle[p,0]= size_x/2
    Particle[p,1]= size_y/2
  endif
next p
          

If we now run the program with this updated loop, we see a never ending stream of particles being emitted from the centre.

Download
Step 6 - Bringing both options together

Hmmmm. In option one the particles come to rest and remain there indefinitely while in option two, the particles are being respawned. How can we combine this?
Well, we do this by giving each particle a random lifetime (random between certain limits) and decreasing the lifetime at every loop.
When the lifetime hits zero, we reinitialize the particle.

This lifetime will be a 5th property of the particle, so we have to change the size and the initialization of the array:


Dim Particle (300,5) #define a 300 particle system with 5 properties
and
for p = 0 to Partnum-1
  Particle[p,0] = size_x/2
  Particle[p,1]= size_y/2 # as we have gravity, we can moe this higher (eg size_y/6)
  Particle[p,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
  Particle[p,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
  Particle[p,4]= rand *1020 # play with this setting until you get a nice bouncy effect
next p
          

Now that we have a life property (Particle[p,4]), we also need to decrease it so we check for viability and if dead (ie life < 0), we reinitialize the particle:


for p = 0 to Partnum-1 #write the particles to the buffer and update them
  color white
  plot (Particle[p,0],Particle[p,1])
  Particle[p,0]= Particle[p,0]+Particle[p,2]
  if Particle[p,0]<0 or Particle [p,0]>size_x then Particle[p,2]= -Particle[p,2]* (0.7+rand/5)
  Particle[p,1]= Particle[p,1]+Particle[p,3]
  if Particle[p,1] < 0 then Particle[p,3]= - Particle[p,3] # bounce off ceiling
  if Particle [p,1]>size_y then Particle[p,3]= - Particle[p,3]* (0.5+rand/5)#bounce + dampen
  Particle[p,3]= Particle[p,3]+grav # artificial gravity
  Particle[p,4]= Particle[p,4]-1
  if Particle[p,4]<0 then
    Particle[p,0] = size_x/2
    Particle[p,1]= size_y/2
    Particle[p,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[p,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[p,4]= rand *1020# play with this setting until you get a nice bouncy effect
  endif
next p
          
Download
Step 7 - Color Managment

currently, all particles are simply white. Based on the life parameter however, we can easily make the particles change color as they age.
There are of course many ways to map the age to a color. We will simply translate the age value to RGB colors.
Simply replace the following code:


color white
          

with the following code:


 age=((Particle[p,4]/4) mod 255)
  if age > 85 then
     colblue = 255
     colgreen = 255
     colred = 255
     color rgb(colred,colgreen,colblue)
  else
    if age >170 then
       colblue = Particle[p,4] mod 255
       colgreen = 255
       colred = 255
       color rgb(colred,colgreen,colblue)
    else
      colblue = 0
      colgreen = Particle[p,4] mod 255
      colred = 255
      color rgb(colred,colgreen,colblue)
    endif
  endif 
          
Download
Step 8 - Initial burst

The initial burst (the square full of particles that appears and bounces before the fountain really kicks in) is because we start the program by initializing all the particles in the system.
This of course also causes all particles to be alive at the chosen position at step 0.
To prevent this, we need to spawn particles all the time on the fly (and not just when one particle dies since then we'd have to wait for the initial particles to start dying first..)

For this, we replace the initialization of the Particle system so that all particles are DEAD (ie Particle [p,4]=0)


for p = 0 to Partnum - 1
  Particle[p,4] = 0
next p
          

Then, during the main loop, the first thing we do is to continuously create a number of particles (here, 3 particles at every iteration). The number of particles here will depend on the total number and on the power of your PC.


for k = 1 to 3
  spawni=int(rand * Partnum) # select a random particle
  if Particle[spawni,4] = 0 then # if the particle is dead, create one
    Particle[spawni,0] = size_x/2
    Particle[spawni,1]= size_y/2
    Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[spawni,4]= rand *1020 # play with this setting
  end if
next k
          

In the next loop (where we update the particles) we first check if the particle in question is dead and if so skip the rest of the loop.
So ,


for p = 0 to Partnum-1 #write the particles to the buffer and update them
  age=((Particle[p,4]/4) mod 255)
  if age > 85 then
     colblue = 255
     colgreen = 255
     colred = 255
     color rgb(colred,colgreen,colblue)
  else
  ...
  endif
next p
          

would become


for p = 0 to Partnum-1 #write the particles to the buffer and update them
  if Particle[p,4]>0 then
  age=((Particle[p,4]/4) mod 255)
  if age > 85 then
     colblue = 255
     colgreen = 255
     colred = 255
     color rgb(colred,colgreen,colblue)
  else
  ...
  endif
  endif
 endif
next p
          

Voila! That is all there is to it! Mind you, if your PC is very fast and if your particle's life duration is set too high, the piecemeal generation of new partivcles will be so fast that it will look as if the initial square is still there...
Fix this by giving you particles a shorter lifetime when creating them piecemeal but a longer one when respawning dead particles.
With these last changes, if we now run our program (particle07.kbs) we get from frame one, a nice particle fountain.

Download
Step 9 - Finishing touches

However, we did say we were going to control it with our mouse.
Well, this is quite simple! All we need to do is to initialize the x- and y-locations to the mouse positions!
Like this:


Particle[p,0]= size_x/2 
Particle[spwani,0]= size_x/2
Particle[p,1]= size_y/2 
Particle[spwani,1]= size_y/2
          

would then become:

	  
Particle[p,0]= mousex
Particle[spawni,0]= mousex
Particle[p,1]= mousey 
Particle[spawni,1]= mousey
          

Running the program now would immediately start the fountain at location 0,0 (seeing that the mouse coordinates have not yet been initialized).
We can fix this by simply checking if mousex is greater than 0 right at the start of the Loop construct:


Loop:
for k = 1 to 3
  spawni=int(rand * Partnum) # select a random particle
  if Particle[spawni,4] = 0 then # if the particle is dead, create one
    Particle[spawni,0]= mousex
       Particle[spawni,1]= mousey
       Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
    Particle[spawni,4]= rand *1020 # play with this setting
  end if
next k
          

would then become:


Loop:
if mousex > 0 then
  for k = 1 to 3
    spawni=int(rand * Partnum) # select a random particle
    if Particle[spawni,4] = 0 then # if the particle is dead, create one
      Particle[spawni,0]= mousex
      Particle[spawni,1]= mousey
      Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
      Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
      Particle[spawni,4]= rand *1020 # play with this setting
    end if
  next k
endif
          

Voila! We now have Basic-256 program that gives us a nice particle fountain controlled by the mouse!!

Download
Step 10 - visual improvement

If you PC is fast enough, you can swap points for circles. For this, we just add a line in the main loop:


	color rgb(colred,colgreen,colblue)
	plot (Particle[p,0],Particle[p,1])

          

becomes:


	color rgb(colred,colgreen,colblue)
#	plot (Particle[p,0],Particle[p,1])
	circle Particle[p,0],Particle[p,1],2
 
          

You can of course play around with the size of the circles.

Voila! all done! You can now start to experiment with increasing the screen dimension or the number of particles, changing the gravity parameter or the life duration, changing the speed at which particles are ejected (currently, we are using (rand-0.5)/0.5 for both x- and y-directions), etc. etc.

Download

Particle Tutorial 2: Text decay!

Step 1 - Basic-256 Boilerplate

The aim of this particle tutorial, is to have text decay in various ways.
At every interim step, it is the intention to have a working program so that you can see what the results are of the piecemeal changes. You can either cut and paste the code in this document to the Basic-256 code window (although indentation gets lost.) or use the hyperlinks to the example programs.

Basic-256 Boilerplate

For building up our particle system program, we will use the following scaffolding


Fastgraphics # write to video buffer.
size_x=800
size_y=800 # good practice to put every constant in a variable.
graphsize size_x,size_y # feel free to change the size of your canvas
color black
rect 0,0,size_x-1,size_y-1 # start out with a nice black screen.
color white
font "Tahoma",40,100
text 275,350,"Some Text"
refresh # dump the video buffer to screen
#Voila! This gives you a nice canvas to start with.

          

Running this program gives us "Some Text" on a nice black background. Not really exciting yet

Download Code
Particle01 Thumbnail